﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;
using System.Data;
using Log4Net;

namespace PollServer
{
    //加锁生产/消费队列
    public class MsgQueue
    {
        private int _type = -1;
        // 初始信号量计数为0，最大计数为1
        private Semaphore _sem = new Semaphore(1, 1);
        //建立一个队列, 初始1000的容量
        private Queue<object> _queue = new Queue<object>(100);
        //lock 对象
        private object _lockobj = new object();

#region 静态全局
        public static Dictionary<int, MsgQueue> QueueMap = new Dictionary<int, MsgQueue>();
        public static object _obj = new object();
        //单例模式
        public static MsgQueue GetMsgQueue(int type)
        {
            lock (_obj)
            {
                MsgQueue msg;
                if (QueueMap.ContainsKey(type))
                {
                    msg = QueueMap[type];
                }
                else
                {
                    msg = new MsgQueue(type);
                    QueueMap.Add(type, msg);
                }
                return msg;
            }
        }
#endregion

#region 公有方法
        ///////////////////////////////////////////////////////////

        public MsgQueue(int type)
        {
            _type = type;
        }

        public Queue<object> get_queue()
        {
           return _queue;
        }

        public bool empty()
        {
            int ret = _queue.Count;
            return (ret == 0);
        }

        public int size()
        {
            return _queue.Count;
        }

        //获取size量的T 返回实际取的 拉取
        public int push_wait_queue(ref MsgQueue msg, int size)
        {
            int num = 0;
            lock (_lockobj)
            {
                num = _queue.Count;
                while (num == 0)
                {
                    Monitor.Wait(_lockobj);
                    num = _queue.Count;
                }
                //
                Queue<object> queue = msg.get_queue();

                //
                num = size < num ? size : num;
                for (int i = 0; i < num; i++)
                {
                    object node = _queue.Dequeue();
                    queue.Enqueue(node);
                }
            }
            return num;
        }

        //push size量的T
        public void pop_pulse_queue(ref MsgQueue msg, int size)
        {
            lock (_lockobj)
            {
               Queue<object> queue = msg.get_queue();
               int num = queue.Count;
               num = num < size ? num : size;

               for (int i = 0; i < num; i++)
               {
                   object node = queue.Dequeue();
                   _queue.Enqueue(node);
               }
               //释放信号量
               //Monitor.Exit(_lockobj);
               Monitor.PulseAll(_lockobj);
            }
        }
        //push 1 个
        public void push_back(object node)
        {
            lock (_lockobj)
            {
               _queue.Enqueue(node);
               //Monitor.Exit(_lockobj);
               Monitor.PulseAll(_lockobj);
            }
        }
        //pop 1 个
        public object pop_front()
        {
            object node = null;
            lock (_lockobj)
            {
                if (_queue.Count > 0)
                {
                    node = _queue.Dequeue();
                }
            }
            return node;
        }
#endregion

    }
}
